package com.atguigu.lister.error;

import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * Created by 小可乐$ on 2024/9/11$ 18:49$
 * description: 故障解决3：消费端的消息确认，需要先将yaml改为手动quer
 * basicAck：消费成功（唯一标识符，打印信息详细）
 * basicNack：消费失败（唯一标识符，打印信息详细，true：重新放入队列消费）
 * basicReject：根据唯一标识符，进行拒绝（唯一标识符，true：重新放回队列）
 */
/*
正常：123
异常：1246 ，1245，1246发送一次，重新发送两次
* * */
@Component
@Slf4j
public class RabbitMQErrorLister03 {
    public static final String EXCHANGE_DIRECT = "exchange.direct.order";
    public static final String ROUTING_KEY = "order";
    public static final String QUEUE_NAME  = "queue.order";

//    修饰监听方法
    @RabbitListener(
//            设置绑定关系
            bindings = @QueueBinding(
//                    配置消费队列信息：durable设置为true，表示队列持久化，autoDelete设置为false，表示关闭自动删除
                    value = @Queue(value = QUEUE_NAME,durable = "true",autoDelete = "false"),
//                    配置交换机信息:durable 设置为 true 表示队列持久化；autoDelete 设置为 false 表示关闭自动删除
                    exchange = @Exchange(value = EXCHANGE_DIRECT,durable = "true",autoDelete = "false"),
//                    配置路由键信息
                    key = {ROUTING_KEY}
            ))
    public void processMessage(String dataString, Message message, Channel channel) throws IOException {
//        1获取当前消息的deliveryTAG值当别用,唯一标识符
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        System.out.println("11111111");
        try{
            //        2正常业务操作
            log.info("消费端接受的消息内容"+deliveryTag);
            System.out.println("2222222222");

//            int age = 10/0;

//        3给RabbitMQ返回ACK确认信息
            channel.basicAck(deliveryTag,false);
            System.out.println("3333333333333");
        }catch (Exception e){
//        4 获取信息。看当前消息是否被投递过
            Boolean redelivered = message.getMessageProperties().getRedelivered();
            System.out.println("4444444444444444");
            if (!redelivered){
//            5.如果没有被投递过，重新放回队列，重新投递，再试一次
//                basicNack:L给Broker返回NACK信息，表示消息在消费端消费失败，此时Broker的后续操作取决于参数requeue的值,
//                multiple 为true批量返回信息，false，只返回ack信息，      requeue为true，重新返回队列
                channel.basicNack(deliveryTag,false,true);
                System.out.println("55555555555555");
            }else {
//            6、如果已经被投递过，且这一次仍然进入了 catch 块，那么返回拒绝且不再放回队列
//                basicReject：根据指定的deliveryTag，对该消息表示拒绝，false，不会返回队列
                channel.basicReject(deliveryTag,false);
                System.out.println("666666666666666666");
            }
        }
    }

}
